package com.exchange.redis.services.impl;

import com.exchange.redis.services.RedisService;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.SortParameters;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.query.SortQueryBuilder;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service("redisService")
    public class RedisServiceImpl implements RedisService {

    @Resource
    private RedisTemplate<String, ?> redisTemplate;

    @Override
    public boolean set(final String key, final String value) {
        boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
            @Override
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
                connection.set(serializer.serialize(key), serializer.serialize(value));
                return true;
            }
        });
        return result;
    }

    @Override
    public String get(final String key) {
        String result = redisTemplate.execute(new RedisCallback<String>() {
            @Override
            public String doInRedis(RedisConnection connection) throws DataAccessException {
                RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
                byte[] value = connection.get(serializer.serialize(key));
                return serializer.deserialize(value);
            }
        });
        return result;
    }

    @Override
    public boolean expire(final String key, long expire) {
        return redisTemplate.expire(key, expire, TimeUnit.SECONDS);
    }

    @Override
    public boolean remove(final String key) {
        boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
            @Override
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
                connection.del(key.getBytes());
                return true;
            }
        });
        return result;
    }

    /**
     * sortPageList("proList","pro:","createTime",true,false,0,20)//本次分页取前20条数据0-->19
     * @param key
     * @param subKey
     * @param by
     * @param isDesc
     * @param isAlpha
     * @param off
     * @param num
     * @param <T>
     * @return
     * @throws Exception
     */

    public <T> List<T> sortPageList(String key, String subKey, String by, boolean isDesc, boolean isAlpha, int off, int num) throws  Exception{
        SortQueryBuilder<String> builder = SortQueryBuilder.sort(key);
        builder.by(subKey+"*->"+by);
        builder.get("#");
        builder.alphabetical(isAlpha);
        if(isDesc)
            builder.order(SortParameters.Order.DESC);
        builder.limit(off, num);
        List<String> cks = (List<String>) redisTemplate.sort(builder.build());
        List<T> result = new ArrayList<T>();
        for (String ck : cks) {
            //得到项目对象 by(subKey+ck);
        }
        return result;
    }
    @Override
    public boolean zAdd(final String key, Double socre, final String value) {
        boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
            @Override
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
                connection.zAdd(serializer.serialize(key), socre,serializer.serialize(value));
                return true;
            }
        });
        return result;
    }

    @Override
    public boolean zRem(final String key, Double socre, final String value) {
        boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
            @Override
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
                connection.zRem(serializer.serialize(key),serializer.serialize(value));
                return true;
            }
        });
        return result;
    }

    @Override
    public LinkedHashSet<String> zRange(final String key, double min, double max, long offset, long count) {
        LinkedHashSet<String> result = redisTemplate.execute(new RedisCallback<LinkedHashSet<String>  >() {
            @Override
            public LinkedHashSet<String>   doInRedis(RedisConnection connection) throws DataAccessException {
                RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
                Set<byte[]>  byteSet =  connection.zRevRangeByScore(serializer.serialize(key), min,  max,  offset,count);
                LinkedHashSet<String>  stringSet = new LinkedHashSet<String>();
                for (byte[] bytes : byteSet) {
                    stringSet.add(new String(bytes));
                }
                return stringSet;
            }
        });
        return result;
    }

    @Override
    public Long zCount(final String key) {
        Long result = redisTemplate.execute(new RedisCallback<Long>() {
            @Override
            public Long  doInRedis(RedisConnection connection) throws DataAccessException {
                RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
                Long  total =  connection.zCount(serializer.serialize(key),0,System.currentTimeMillis());
                return total;
            }
        });
        return result;
    }

}